#include "TcpServer.hpp"
#include <memory>
#include "Protocal.hpp"
#include "Calculator.hpp"
#include "Daemon.hpp"

using Cal_t = std::function<response(const request &req)>; // 传一个请求，返回一个resp结构化数据
// 处理模块
class Parse
{
public:
    Parse(Cal_t cal) : _cal(cal)
    {
    }
    std::string Entry(std::string &package)
    {
        std::string message;
        std::string respstr;
        while (Decode(package, &message))
        {

            LOG(LogLevel::DEBUG) << "Content: \n"<< message;
            /*if (message.empty())
                break;*/

            // 2. 反序列化， message是一个曾经被序列化的request
            request req;
            /*if (!req.Deserialize(message))
                break*/
            req.Deserialize(message);

            std::cout << "#############" << std::endl;
            req.Print();
            std::cout << "#############" << std::endl;

            // 3. 计算
            response resp = _cal(req);

            // 4. 序列化
            std::string res;
            resp.Serialize(res);
            LOG(LogLevel::DEBUG) << "序列化: \n"
                                 << res;

            // 5. 添加长度报头字段！
            Encode(res);

            LOG(LogLevel::DEBUG) << "Encode: \n"
                                 << res;

            // 6. 拼接应答
            respstr += res;
        }
        LOG(LogLevel::DEBUG) << "respstr: \n"
                             << respstr;
        return respstr;
    }
    ~Parse()
    {
    }

private:
    Cal_t _cal;
};

int main(int argc, char *argv[])
{
    ENABLE_FILE_LOG();
    Daemon(false,false);

    Calculator cal;
    Parse parse([&cal](const request &req)
                { return cal.Execute(req); });

    int server_port = std::stoi(argv[1]);
    // Command com;
    std::unique_ptr<TcpServer> tsvr = std::make_unique<TcpServer>([&parse](std::string &packge)
                                                                  { return parse.Entry(packge); }, server_port);

    tsvr->InitServer();
    tsvr->Start();

    /*request req(10, 20, '+');
    std::string ss;
    req.Serialize(ss);

    std::cout << ss << std::endl;*/

    return 0;
}
